//package tech.heiming.aps.controller;
//
//import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
//import org.optaplanner.core.api.score.stream.Constraint;
//import org.optaplanner.core.api.score.stream.ConstraintFactory;
//import org.optaplanner.core.api.score.stream.ConstraintProvider;
//import org.optaplanner.core.api.score.stream.Joiners;
//import org.springframework.stereotype.Component;
//import tech.heiming.aps.domain.Lesson;
//import tech.heiming.aps.domain.Room;
//
///**
// * @author heimingz
// */
//public class TimeTableConstraintProvider implements ConstraintProvider {
//
//    @Override
//    public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
//        return new Constraint[]{
//                // Hard constraints
//                roomConflict(constraintFactory),
//                teacherConflict(constraintFactory),
//                studentGroupConflict(constraintFactory),
//                lightConflict(constraintFactory),
//                // Soft constraints are only implemented in the "complete" implementation
//        };
//    }
//
//    private Constraint roomConflict(ConstraintFactory constraintFactory) {
//        // A room can accommodate at most one lesson at the same time.
//
//        // Select a lesson ...
//        return constraintFactory.from(Lesson.class)
//                // ... and pair it with another lesson ...
//                .join(Lesson.class,
//                        // ... in the same timeslot ...
//                        Joiners.equal(Lesson::getTimeslot),
//                        // ... in the same room ...
//                        Joiners.equal(Lesson::getRoom),
//                        // ... and the pair is unique (different id, no reverse pairs)
//                        Joiners.lessThan(Lesson::getId))
//                // then penalize each pair with a hard weight.
//                .penalize("Room conflict", HardSoftScore.ONE_HARD);
//    }
//
//    private Constraint teacherConflict(ConstraintFactory constraintFactory) {
//        // A teacher can teach at most one lesson at the same time.
//        return constraintFactory.from(Lesson.class)
//                .join(Lesson.class,
//                        Joiners.equal(Lesson::getTimeslot),
//                        Joiners.equal(Lesson::getTeacher),
//                        Joiners.lessThan(Lesson::getId))
//                .penalize("Teacher conflict", HardSoftScore.ONE_HARD);
//    }
//
//    private Constraint studentGroupConflict(ConstraintFactory constraintFactory) {
//        // A student can attend at most one lesson at the same time.
//        return constraintFactory.from(Lesson.class)
//                .join(Lesson.class,
//                        Joiners.equal(Lesson::getTimeslot),
//                        Joiners.equal(Lesson::getStudentGroup),
//                        Joiners.lessThan(Lesson::getId))
//                .penalize("Student group conflict", HardSoftScore.ONE_HARD);
//    }
//
//    private Constraint lightConflict(ConstraintFactory constraintFactory) {
//        // A student can attend at most one lesson at the same time.
//        return constraintFactory.from(Room.class)
//                .join(Room.class,
//                        Joiners.equal(Room::getLight),
//                        Joiners.lessThan(Room::getName))
//                .penalize("Room group conflict", HardSoftScore.ONE_HARD);
//    }
//}
